package com.p7.framework.permission.shiro;

import java.io.Serializable;

import javax.servlet.ServletRequest;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.p7.framework.permission.shiro.session.ClientCachingSessionDAO;

public class CustomDefaultWebSessionManager extends DefaultWebSessionManager{
	
	private static final Logger LOGGER = LoggerFactory.getLogger(CustomDefaultWebSessionManager.class);

	/**
	 * 优化单次请求需要多次访问redis的问题，注意是单次请求
	 * @param sessionKey
	 * @return
	 * @throws UnknownSessionException
	 */
	@Override
	protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
		Serializable sessionId = getSessionId(sessionKey);
		ServletRequest request = null;
		if (sessionKey instanceof WebSessionKey) {
			request = ((WebSessionKey) sessionKey).getServletRequest();
		}
		if (request != null && sessionId != null) {
			Object sessionObj = request.getAttribute(sessionId.toString());
			if (sessionObj != null) {
				return (Session) sessionObj;
			}
		}
		Session session = super.retrieveSession(sessionKey);
		if (request != null && null != sessionId) {
			request.setAttribute(sessionId.toString(), session);
		}
		return session;
	}


	/**
	 * 此方法是shiroFilter默认调用的方法，每次有请求都会调用此方法，在AbstractNativeSessionManager中有实现，即更新redis中的session信息。
	 * 覆盖此方法的目的：本地缓存失效后才去redis拉取session信息。super.touch方法中调用了DefaultSessionManager#onChange方法
	 * onChange方法调用了sessionDAO.update(session)更新session信息，这里的sessionDao=ClientCachingSessionDAO，
	 * ClientCachingSessionDAO的update方法调用doUpdate方法，如果session中有属性值设置和移除，都会触发redis session更新，
	 * 同时更新本地缓存
	 * @param key
	 * @throws InvalidSessionException
	 */
	// @Override
	// public void touch(SessionKey key) throws InvalidSessionException {

	// 	ClientCachingSessionDAO sessionDAO = (ClientCachingSessionDAO) this.sessionDAO;
	// 	Cache<Serializable, Session> cache = sessionDAO.getCache();

	// 	if(cache != null){
	// 		Session cacheSession = cache.get(key.getSessionId());
	// 		LOGGER.info("cache session : {}" , JSON.toJSONString(cacheSession));
	// 		if(cacheSession == null){
	// 			super.touch(key);
	// 		}
	// 	}else{
	// 		super.touch(key);
	// 	}
	// }
}
